package com.example.logaspect.aspect;

import com.example.logaspect.annotation.LogRecord.LogLevel;
import com.example.logaspect.config.LogAspectProperties;
import com.example.logaspect.service.LogRecordService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;

import java.lang.reflect.Method;

/**
 * 全局日志切面（无需注解）
 */
@Aspect
@Order(2)
public class GlobalLogAspect {

    private final LogRecordService logRecordService;
    private final LogAspectProperties properties;

    public GlobalLogAspect(LogRecordService logRecordService, LogAspectProperties properties) {
        this.logRecordService = logRecordService;
        this.properties = properties;
    }

    @Pointcut("execution(* *.*(..))")
    public void defaultPointcut() {}

    @Around("defaultPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 如果切面被禁用，直接执行目标方法
        if (!properties.isEnabled() || !properties.isEnableGlobalAspect()) {
            return joinPoint.proceed();
        }

        // 获取方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String className = method.getDeclaringClass().getName();

        // 检查是否需要排除
        for (String excludePackage : properties.getExcludePackages()) {
            if (className.startsWith(excludePackage)) {
                return joinPoint.proceed();
            }
        }

        // 方法入参
        Object[] args = joinPoint.getArgs();
        String methodSignature = className + "." + method.getName();

        // 记录方法开始执行
        if (properties.isRecordParams()) {
            logRecordService.recordMethodStart(methodSignature, "", args, LogLevel.INFO);
        } else {
            logRecordService.recordMethodStart(methodSignature, "", null, LogLevel.INFO);
        }

        // 执行时间
        long startTime = System.currentTimeMillis();
        Object result = null;

        try {
            // 执行目标方法
            result = joinPoint.proceed();

            // 计算执行时间
            long executionTime = System.currentTimeMillis() - startTime;

            // 记录方法执行完成
            if (properties.isRecordExecutionTime()) {
                if (properties.isRecordResult()) {
                    logRecordService.recordMethodEnd(methodSignature, "",
                            properties.isRecordParams() ? args : null,
                            result, executionTime, LogLevel.INFO);
                } else {
                    logRecordService.recordMethodEnd(methodSignature, "",
                            properties.isRecordParams() ? args : null,
                            null, executionTime, LogLevel.INFO);
                }
            }

            return result;
        } catch (Throwable throwable) {
            // 记录异常
            long executionTime = System.currentTimeMillis() - startTime;
            logRecordService.recordMethodException(methodSignature, "",
                    properties.isRecordParams() ? args : null,
                    throwable, executionTime, LogLevel.ERROR);
            throw throwable;
        }
    }
}